package com.loopstack.gprint.io;

import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.os.SystemClock;
import android.os.Build.VERSION;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.RequiresApi;
import androidx.core.app.ActivityCompat;

import com.loopstack.gprint.utils.CallbackListener;
import com.loopstack.gprint.utils.Command;
import com.loopstack.gprint.utils.GpUtils;
import com.loopstack.gprint.utils.HexUtils;
import com.loopstack.gprint.utils.LogUtils;
import com.loopstack.gprint.io.PortManager;
import com.loopstack.gprint.io.PrinterDevices;
import com.loopstack.gprint.utils.SDKUtils;
import com.loopstack.gprint.utils.UIThreadManager;
import com.loopstack.gprint.utils.PDFUtils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
import java.util.Vector;

public class BleBlueToothPort extends PortManager {
    private String TAG = BleBlueToothPort.class.getSimpleName();
    private String mac;
    private CallbackListener callbackListener;
    private Context context;
    private int id;
    private BluetoothAdapter bluetoothAdapter = null;
    private String SERVICES_UUID = "49535343-fe7d-4ae5-8fa9-9fafd205e455";
    private String WRITE_UUID = "49535343-8841-43f4-a8d4-ecbe34729bb3";
    private String NOTIFY_UUID = "49535343-1e4D-4bd9-ba61-23c647249616";
    private BluetoothGattCharacteristic writeCharacteristic;
    private BluetoothGattCharacteristic notifyCharacteristic;
    private BluetoothGatt bluetoothGatt;
    private Command command;
    private BluetoothDevice mDevices = null;
    private BleGattCallback mGattCallback;
    private int SINGLE_SIZE = 20;
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    private final Object lock = new Object();
    private PrinterDevices mPrinterDevices = null;

    public BleBlueToothPort(PrinterDevices printerDevices) {
        if (printerDevices != null) {
            this.mPrinterDevices = printerDevices;
            this.context = printerDevices.getContext();
            this.id = printerDevices.getId();
            this.mac = printerDevices.getMacAddress();
            this.command = printerDevices.getCommand();
            this.callbackListener = printerDevices.getCallbackListener();
            this.SINGLE_SIZE = printerDevices.getBle();
        }

    }

    private void setSuccessListen(Command command) {
        this.command = command;
        this.mPrinterDevices.setCommand(command);
        if (this.callbackListener != null) {
            UIThreadManager.onUIThread(new Runnable() {
                public void run() {
                    BleBlueToothPort.this.callbackListener.onSuccess(BleBlueToothPort.this.mPrinterDevices);
                }
            });
        }

    }

    private void setFailureListen() {
        if (this.callbackListener != null) {
            UIThreadManager.onUIThread(new Runnable() {
                public void run() {
                    BleBlueToothPort.this.callbackListener.onFailure();
                }
            });
        }

    }

    private void checkPrinterCommand() throws IOException {
        int status = this.getPrinterStatus(Command.ESC);
        if (status == -1) {
            status = this.getPrinterStatus(Command.CPCL);
            if (status == -1) {
                status = this.getPrinterStatus(Command.TSC);
                if (status == -1) {
                    this.setFailureListen();
                } else {
                    this.setSuccessListen(Command.TSC);
                }
            } else {
                this.setSuccessListen(Command.CPCL);
            }
        } else {
            this.setSuccessListen(Command.ESC);
        }

    }

    private void getFeasycomCharacteristic(BluetoothGattService service) {
        Iterator var2 = service.getCharacteristics().iterator();

        while (var2.hasNext()) {
            BluetoothGattCharacteristic characteristic = (BluetoothGattCharacteristic) var2.next();
            int charaProp = characteristic.getProperties();
            if ((charaProp & 16) != 0) {
                Log.e(this.TAG, "发现NOTIFY特征值" + characteristic.getUuid().toString());
                if (characteristic.getUuid().toString().equals(this.NOTIFY_UUID)) {
                    this.notifyCharacteristic = characteristic;
                } else {
                    Log.e(this.TAG, "getFeasycomCharacteristic: 1");
                    Log.e(this.TAG, "getFeasycomCharacteristic: 2");
                }
            }

            if ((charaProp & 8) != 0) {
                Log.e(this.TAG, "发现Write Without Response特征值" + characteristic.getUuid().toString());
                if (this.writeCharacteristic == null) {
                    Log.e(this.TAG, "setCharacteristic: ");
                    this.writeCharacteristic = characteristic;
                }
            }
        }

        if (this.writeCharacteristic == null) {
            List<BluetoothGattCharacteristic> characteristicList = service.getCharacteristics();
            Iterator var7 = characteristicList.iterator();

            while (var7.hasNext()) {
                BluetoothGattCharacteristic characteristic = (BluetoothGattCharacteristic) var7.next();
                Log.e(this.TAG, "发现Witer特征值" + characteristic.getUuid().toString());
                int charaProp = characteristic.getProperties();
                if ((charaProp & 4) != 0) {
                    Log.e(this.TAG, "setCharacteristic: ");
                    this.writeCharacteristic = characteristic;
                }
            }
        }

    }

    private boolean enableNotification(boolean enable, BluetoothGattCharacteristic characteristic) {
        if (this.bluetoothGatt != null && characteristic != null) {
            if (!this.bluetoothGatt.setCharacteristicNotification(characteristic, enable)) {
                return false;
            } else {
                BluetoothGattDescriptor clientConfig = characteristic.getDescriptor(UUID.fromString(this.NOTIFY_UUID));
                if (clientConfig == null) {
                    return false;
                } else {
                    if (enable) {
                        clientConfig.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                    } else {
                        clientConfig.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
                    }

                    return this.bluetoothGatt.writeDescriptor(clientConfig);
                }
            }
        } else {
            return false;
        }
    }

    @Override
    public boolean openPort() {
        UIThreadManager.onUIThread(new Runnable() {
            public void run() {
                if (BleBlueToothPort.this.callbackListener != null) {
                    BleBlueToothPort.this.callbackListener.onConnecting();
                }

            }
        });
        if (!this.context.getPackageManager().hasSystemFeature("android.hardware.bluetooth_le")) {
            UIThreadManager.onUIThread(new Runnable() {
                public void run() {
                    if (BleBlueToothPort.this.callbackListener != null) {
                        BleBlueToothPort.this.callbackListener.onFailure();
                    }

                }
            });
            return false;
        } else {
            this.bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
            if (this.bluetoothAdapter != null && this.bluetoothAdapter.isEnabled()) {
                this.mDevices = this.bluetoothAdapter.getRemoteDevice(this.mac);
                this.mPrinterDevices.setBlueName(this.mDevices.getName());
                if (this.mDevices == null) {
                    UIThreadManager.onUIThread(new Runnable() {
                        public void run() {
                            if (BleBlueToothPort.this.callbackListener != null) {
                                BleBlueToothPort.this.callbackListener.onFailure();
                            }

                        }
                    });
                }

                this.mGattCallback = new BleGattCallback();
                if (VERSION.SDK_INT >= 23) {
                    this.bluetoothGatt = this.mDevices.connectGatt(this.context, false, this.mGattCallback, 2);
                } else {
                    this.bluetoothGatt = this.mDevices.connectGatt(this.context, false, this.mGattCallback);
                }

                return false;
            } else {
                UIThreadManager.onUIThread(new Runnable() {
                    public void run() {
                        if (BleBlueToothPort.this.callbackListener != null) {
                            BleBlueToothPort.this.callbackListener.onFailure();
                        }

                    }
                });
                throw new RuntimeException("The device does not support Bluetooth！");
            }
        }
    }

    public void setCommand(Command command) {
        this.command = command;
    }

    public PrinterDevices getPrinterDevices() {
        return this.mPrinterDevices;
    }

    public Command getCommand() {
        return this.command;
    }

    public void setBlePack(int pack) {
        synchronized (this.lock) {
            this.SINGLE_SIZE = pack;
        }
    }

    public boolean writeDataImmediately(byte[] data, Context context) throws IOException {
        if (this.writeCharacteristic == null) {
            Log.e(this.TAG, "读写特征值为空,尝试获取特征值");
            List<BluetoothGattService> list = this.getSupportedGattServices();

            for (int i = 0; i < list.size(); ++i) {
                this.getFeasycomCharacteristic((BluetoothGattService) list.get(i));
            }
        }

        if (this.writeCharacteristic == null) {
            return false;
        } else {
            int offset = 0;
            List<byte[]> mlist = SDKUtils.getListByteArray(data, this.SINGLE_SIZE);
            int packNum = 0;

            while (packNum < mlist.size()) {
                this.writeCharacteristic.setValue((byte[]) mlist.get(packNum));
                boolean result = this.bluetoothGatt.writeCharacteristic(this.writeCharacteristic);
                Log.e(this.TAG, "send result" + result);
                if (result) {
                    offset += ((byte[]) mlist.get(packNum)).length;
                    ++packNum;
                } else {
                    Log.e(this.TAG, "send error");

                    try {
                        Thread.sleep(15L);
                    } catch (InterruptedException var7) {
                        var7.printStackTrace();
                    }
                }

                if (this.writeCharacteristic == null) {
                    Log.e(this.TAG, "Interrupt transmission");
                    break;
                }
            }

            mlist.clear();
            if (offset == data.length) {
                Log.e(this.TAG, "send success");
                return true;
            } else {
                return false;
            }
        }
    }

    @RequiresApi(
            api = 21
    )
    public boolean writePDFToEsc(File file, int width) throws Exception {
        Bitmap[] bitmaps = PDFUtils.PDFToBitmap(file, width);
        if (bitmaps == null) {
            return false;
        } else {
            for(int i = 0; i < bitmaps.length; ++i) {
                byte[] data = PDFUtils.drawEscPDF(bitmaps[i]);
                this.writeDataImmediately(data);
                if (i == bitmaps.length - 1) {
                    return true;
                }
            }

            byte[] command = new byte[]{10, 29, 86, 66, 0, 27, 64};
            this.writeDataImmediately(command);
            return false;
        }
    }

    @RequiresApi(
            api = 21
    )
    public boolean writePDFToTsc(File file, int printWidth, int gap, boolean cut, boolean dpi200, boolean compression, int cutHeight) throws Exception {
        if (file == null) {
            throw new Exception("File cannot be empty");
        } else if (TextUtils.isEmpty(String.valueOf(printWidth))) {
            throw new Exception("printWidth cannot be empty");
        } else if (TextUtils.isEmpty(String.valueOf(gap))) {
            throw new Exception("gap cannot be empty");
        } else if (TextUtils.isEmpty(String.valueOf(cutHeight))) {
            throw new Exception("cutHeight cannot be empty");
        } else {
            Bitmap[] bitmaps = PDFUtils.PDFToBitmap(file, printWidth);
            if (bitmaps == null) {
                return false;
            } else {
                int i;
                String cls;
                String print;
                if (gap > 0 | cutHeight == 0) {
                    for(i = 0; i < bitmaps.length; ++i) {
                        String size = "\r\nSIZE " + bitmaps[i].getWidth() / (dpi200 ? 8 : 12) + " mm," + bitmaps[i].getHeight() / (dpi200 ? 8 : 12) + " mm\r\n";
                        this.writeDataImmediately(size.getBytes("GB18030"));
                        String GAP = "GAP " + gap + " mm,0 mm\r\n";
                        if (cut && i == bitmaps.length - 1) {
                            this.writeDataImmediately("SET CUTTER 1\r\n".getBytes("GB18030"));
                        } else {
                            this.writeDataImmediately("SET CUTTER OFF\r\n".getBytes("GB18030"));
                        }

                        this.writeDataImmediately(GAP.getBytes("GB18030"));
                        cls = "CLS\r\n";
                        this.writeDataImmediately(cls.getBytes("GB18030"));
                        byte[] data;
                        if (compression) {
                            data = PDFUtils.drawTscPDFLib(bitmaps[i]);
                            this.writeDataImmediately(data);
                        } else {
                            data = PDFUtils.drawTscPDF(bitmaps[i]);
                            this.writeDataImmediately(data);
                        }

                        print = "\r\nPRINT 1\r\n";
                        this.writeDataImmediately(print.getBytes("GB18030"));
                        if (i == bitmaps.length - 1) {
                            return true;
                        }
                    }
                } else {
                    for(i = 0; i < bitmaps.length; ++i) {
                        List<Bitmap> mlist = ImageCrop(bitmaps[i], cutHeight);

                        for(int j = 0; j < mlist.size(); ++j) {
                            cls = "\r\nSIZE " + ((Bitmap)mlist.get(j)).getWidth() / (dpi200 ? 8 : 12) + " mm," + ((Bitmap)mlist.get(j)).getHeight() / (dpi200 ? 8 : 12) + " mm\r\n";
                            this.writeDataImmediately(cls.getBytes("GB18030"));
                            String GAP = "GAP 0 mm,0 mm\r\n";
                            if (cut && j == mlist.size() - 1 && i == bitmaps.length - 1) {
                                this.writeDataImmediately("SET CUTTER 1\r\n".getBytes("GB18030"));
                            } else {
                                this.writeDataImmediately("SET CUTTER OFF\r\n".getBytes("GB18030"));
                            }

                            this.writeDataImmediately(GAP.getBytes("GB18030"));
                            print = "CLS\r\n";
                            this.writeDataImmediately(print.getBytes("GB18030"));
                            byte[] data;
                            if (compression) {
                                data = PDFUtils.drawTscPDFLib((Bitmap)mlist.get(j));
                                this.writeDataImmediately(data);
                            } else {
                                data = PDFUtils.drawTscPDF((Bitmap)mlist.get(j));
                                this.writeDataImmediately(data);
                            }

                            print = "\r\nPRINT 1\r\n";
                            this.writeDataImmediately(print.getBytes("GB18030"));
                        }

                        if (i == bitmaps.length - 1) {
                            mlist.clear();
                            return true;
                        }
                    }
                }

                return false;
            }
        }
    }

    public boolean writeBitmapToTsc(Bitmap mBitmap, int printWidth, boolean cut, boolean dpi200, boolean compression, int cutHeight) throws Exception {
        if (mBitmap == null) {
            throw new Exception("Bitmap cannot be empty");
        } else if (TextUtils.isEmpty(String.valueOf(printWidth))) {
            throw new Exception("printWidth cannot be empty");
        } else if (TextUtils.isEmpty(String.valueOf(cutHeight))) {
            throw new Exception("cutHeight cannot be empty");
        } else {
            if (mBitmap != null) {
                int width = (printWidth + 7) / 8 * 8;
                int height = mBitmap.getHeight() * width / mBitmap.getWidth();
                Log.d("BMP", "bmp.getWidth() " + mBitmap.getWidth());
                Bitmap rszBitmap = GpUtils.resizeImage(mBitmap, width, height);
                List<Bitmap> mlist = ImageCrop(rszBitmap, cutHeight);

                for(int j = 0; j < mlist.size(); ++j) {
                    String size = "\r\nSIZE " + ((Bitmap)mlist.get(j)).getWidth() / (dpi200 ? 8 : 12) + " mm," + ((Bitmap)mlist.get(j)).getHeight() / (dpi200 ? 8 : 12) + " mm\r\n";
                    this.writeDataImmediately(size.getBytes("GB18030"));
                    String gap = "GAP 0 mm,0 mm\r\n";
                    this.writeDataImmediately(gap.getBytes("GB18030"));
                    if (cut && j == mlist.size() - 1) {
                        this.writeDataImmediately("SET CUTTER 1\r\n".getBytes("GB18030"));
                    } else {
                        this.writeDataImmediately("SET CUTTER OFF\r\n".getBytes("GB18030"));
                    }

                    String cls = "CLS\r\n";
                    this.writeDataImmediately(cls.getBytes("GB18030"));
                    byte[] data = PDFUtils.drawTscPDFLib((Bitmap)mlist.get(j));
                    this.writeDataImmediately(data);
                    String print = "\r\nPRINT 1\r\n";
                    this.writeDataImmediately(print.getBytes("GB18030"));
                    if (j == mlist.size() - 1) {
                        return true;
                    }
                }
            }

            return false;
        }
    }

    public static List<Bitmap> ImageCrop(Bitmap bitmap, int photoheight) {
        List<Bitmap> list = new ArrayList();
        int last = bitmap.getHeight() % photoheight;

        for (int i = 0; i < bitmap.getHeight() - bitmap.getHeight() % photoheight; i += photoheight) {
            list.add(cutBitmap(bitmap, i, photoheight));
        }

        if (last > 0) {
            Bitmap cp = cutBitmap(bitmap, bitmap.getHeight() - bitmap.getHeight() % photoheight, bitmap.getHeight() % photoheight);
            list.add(cp);
        }

        return list;
    }

    public static Bitmap cutBitmap(Bitmap bitmap, int y, int height) {
        int w = bitmap.getWidth();
        int h = bitmap.getHeight();
        Log.e(String.valueOf(w), String.valueOf(h));
        return Bitmap.createBitmap(bitmap, 0, y, w, height, (Matrix) null, false);
    }

    public int getPrinterStatus(Command command) throws IOException {
        if (command == null) {
            return -1;
        } else {
            synchronized (this.lock) {
                if (this.byteArrayOutputStream.size() > 0) {
                    this.byteArrayOutputStream.reset();
                }
            }

            byte[] recv;
            switch (command) {
                case ESC:
                    byte[] esc = new byte[]{16, 4, 2};
                    this.writeDataImmediately(esc);
                    break;
                case TSC:
                    byte[] tsc = new byte[]{27, 33, 63, 13, 10};
                    this.writeDataImmediately(tsc);
                    break;
                case CPCL:
                    recv = new byte[]{27, 104};
                    this.writeDataImmediately(recv);
            }

            long endTime = SystemClock.uptimeMillis() + 2000L;
            recv = new byte[1];
            int len = 0;
            if (this.writeCharacteristic == null) {
                while (len <= 0) {
                    try {
                        Thread.sleep(100L);
                    } catch (InterruptedException var10) {
                    }

                    if (endTime <= SystemClock.uptimeMillis()) {
                        break;
                    }
                }
            } else {
                synchronized (this.lock) {
                    while (this.byteArrayOutputStream.size() == 0 && endTime > SystemClock.uptimeMillis()) {
                        try {
                            this.lock.wait(500L);
                        } catch (InterruptedException var9) {
                        }
                    }

                    if (this.byteArrayOutputStream != null && this.byteArrayOutputStream.size() > 0) {
                        len = this.byteArrayOutputStream.size();
                        recv = this.byteArrayOutputStream.toByteArray();
                    }
                }

                LogUtils.e("status" + len);
            }

            if (len > 0) {
                switch (command) {
                    case ESC:
                        if (recv[0] == 18) {
                            return 0;
                        }

                        if ((recv[0] & 32) > 0) {
                            return -2;
                        }

                        if ((recv[0] & 4) > 0) {
                            return -3;
                        }

                        if ((recv[0] & 64) > 0) {
                            return -4;
                        }
                        break;
                    case TSC:
                        if (recv[0] == 0) {
                            return 0;
                        }

                        if ((recv[0] & 32) > 0) {
                            return 1;
                        }

                        if ((recv[0] & 4) > 0) {
                            return -2;
                        }

                        if ((recv[0] & 1) > 0) {
                            return -3;
                        }

                        if ((recv[0] & 128) > 0) {
                            return -4;
                        }

                        if ((recv[0] & 2) > 0) {
                            return -5;
                        }

                        if ((recv[0] & 3) > 0) {
                            return -6;
                        }

                        if ((recv[0] & 5) > 0) {
                            return -7;
                        }

                        if ((recv[0] & 8) > 0) {
                            return -8;
                        }

                        if ((recv[0] & 9) > 0) {
                            return -9;
                        }

                        if ((recv[0] & 10) > 0) {
                            return -10;
                        }

                        if ((recv[0] & 11) > 0) {
                            return -11;
                        }

                        if ((recv[0] & 12) > 0) {
                            return -12;
                        }

                        if ((recv[0] & 13) > 0) {
                            return -13;
                        }

                        if ((recv[0] & 16) > 0) {
                            return -14;
                        }
                        break;
                    case CPCL:
                        if (recv[0] == 0) {
                            return 0;
                        }

                        if ((recv[0] & 1) > 0) {
                            return 1;
                        }

                        if (recv[0] == 2) {
                            return -2;
                        }

                        if (recv[0] == 4) {
                            return -3;
                        }

                        if (recv[0] == 6) {
                            return -4;
                        }
                }

                return recv[0] & 255;
            } else {
                return -1;
            }
        }
    }

    public int getPower() throws IOException {
        synchronized (this.lock) {
            if (this.byteArrayOutputStream.size() > 0) {
                this.byteArrayOutputStream.reset();
            }
        }

        byte[] command = new byte[]{31, 27, 31, -88, 16, 17, 18, 19, 20, 21, 119};
        this.writeDataImmediately(command);
        long endTime = SystemClock.uptimeMillis() + 2000L;
        byte[] recv = new byte[1];
        int len = 0;
        if (this.writeCharacteristic == null) {
            while (len <= 0) {
                try {
                    Thread.sleep(100L);
                } catch (InterruptedException var10) {
                }

                if (endTime <= SystemClock.uptimeMillis()) {
                    break;
                }
            }
        } else {
            synchronized (this.lock) {
                while (this.byteArrayOutputStream.size() == 0 && endTime > SystemClock.uptimeMillis()) {
                    try {
                        this.lock.wait(500L);
                    } catch (InterruptedException var9) {
                    }
                }

                if (this.byteArrayOutputStream != null && this.byteArrayOutputStream.size() > 0) {
                    len = this.byteArrayOutputStream.size();
                    recv = this.byteArrayOutputStream.toByteArray();
                }
            }

            LogUtils.e("status" + len);
        }

        if (len > 0) {
            if (recv[0] == 49) {
                return 1;
            }

            if (recv[0] == 50) {
                return 2;
            }

            if (recv[0] == 51) {
                return 3;
            }

            if (recv[0] == 52) {
                return 4;
            }

            if (recv[0] == 53) {
                return 5;
            }
        }

        return -1;
    }

    public String getPrinterModel(Command command) throws IOException {
        if (command == null) {
            return "";
        } else {
            synchronized (this.lock) {
                if (this.byteArrayOutputStream.size() > 0) {
                    this.byteArrayOutputStream.reset();
                }
            }

            byte[] recv;
            switch (command) {
                case ESC:
                    byte[] esc = new byte[]{29, 73, 67};
                    this.writeDataImmediately(esc);
                    break;
                case TSC:
                    byte[] tsc = new byte[]{126, 33, 84, 13, 10};
                    this.writeDataImmediately(tsc);
                    break;
                case CPCL:
                    recv = new byte[]{27, 118};
                    this.writeDataImmediately(recv);
            }

            long endTime = SystemClock.uptimeMillis() + 2000L;
            recv = new byte[32];
            int len = 0;
            if (this.writeCharacteristic == null) {
                while (len <= 0) {
                    try {
                        Thread.sleep(100L);
                    } catch (InterruptedException var10) {
                    }

                    if (endTime <= SystemClock.uptimeMillis()) {
                        break;
                    }
                }
            } else {
                synchronized (this.lock) {
                    while (endTime > SystemClock.uptimeMillis()) {
                        try {
                            this.lock.wait(500L);
                        } catch (InterruptedException var9) {
                        }
                    }

                    if (this.byteArrayOutputStream != null && this.byteArrayOutputStream.size() > 0) {
                        len = this.byteArrayOutputStream.size();
                        recv = this.byteArrayOutputStream.toByteArray();
                    }
                }

                LogUtils.e("status" + len);
            }

            return recv.length > 0 ? new String(recv) : null;
        }
    }

    public boolean writeDataImmediately(Vector<Byte> sendData) throws IOException {
        if (this.writeCharacteristic == null) {
            Log.e(this.TAG, "读写特征值为空,尝试获取特征值");
            List<BluetoothGattService> list = this.getSupportedGattServices();

            for (int i = 0; i < list.size(); ++i) {
                this.getFeasycomCharacteristic((BluetoothGattService) list.get(i));
            }
        }

        if (this.writeCharacteristic == null) {
            return false;
        } else {
            int offset = 0;
            byte[] data = SDKUtils.convertVectorByteToBytes(sendData);
            List<byte[]> mlist = SDKUtils.getListByteArray(data, this.SINGLE_SIZE);
            int packNum = 0;

            while (packNum < mlist.size()) {
                this.writeCharacteristic.setValue((byte[]) mlist.get(packNum));
                boolean result = this.bluetoothGatt.writeCharacteristic(this.writeCharacteristic);
                Log.e(this.TAG, "send result" + result);
                if (result) {
                    offset += ((byte[]) mlist.get(packNum)).length;
                    ++packNum;
                } else {
                    Log.e(this.TAG, "send error");

                    try {
                        Thread.sleep(30L);
                    } catch (InterruptedException var8) {
                        var8.printStackTrace();
                    }
                }

                if (this.writeCharacteristic == null) {
                    Log.e(this.TAG, "Interrupt transmission");
                    break;
                }
            }

            sendData.clear();
            mlist.clear();
            if (offset == data.length) {
                Log.e(this.TAG, "send success");
                return true;
            } else {
                return false;
            }
        }
    }

    public List<BluetoothGattService> getSupportedGattServices() {
        return this.bluetoothGatt == null ? null : this.bluetoothGatt.getServices();
    }

    public int readData(byte[] bytes) throws IOException {
        return super.readData(bytes);
    }

    @RequiresApi(
            api = 18
    )
    public synchronized boolean closePort() {
        Log.e(this.TAG, "closePort BLE_BLUETooth");
        this.mPrinterDevices = null;
        this.writeCharacteristic = null;
        if (this.bluetoothGatt != null) {
            this.bluetoothGatt.disconnect();
            this.bluetoothGatt.close();
        }

        return true;
    }

    @RequiresApi(
            api = 18
    )
    private class BleGattCallback extends BluetoothGattCallback {
        private BleGattCallback() {
        }

        public void onConnectionStateChange(BluetoothGatt gatt, final int status, final int newState) {
            if (BleBlueToothPort.this.callbackListener != null) {
                UIThreadManager.onUIThread(new Runnable() {
                    public void run() {
                        if (status == 0) {
                            switch (newState) {
                                case 1:
                                    BleBlueToothPort.this.callbackListener.onConnecting();
                                    break;
                                case 2:
                                    BleBlueToothPort.this.bluetoothGatt.discoverServices();
                            }

                        } else {
                            String err;
                            if (status == 8) {
                                BleBlueToothPort.this.closePort();
                                err = "Cannot connect device with error status: " + status;
                                Log.e(BleBlueToothPort.this.TAG, err);
                                BleBlueToothPort.this.callbackListener.onDisconnect();
                            } else {
                                BleBlueToothPort.this.closePort();
                                err = "Cannot connect device with error status: " + status;
                                Log.e(BleBlueToothPort.this.TAG, err);
                                BleBlueToothPort.this.callbackListener.onFailure();
                            }

                        }
                    }
                });
            }

        }

        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            super.onServicesDiscovered(gatt, status);
            List<BluetoothGattService> services = BleBlueToothPort.this.bluetoothGatt.getServices();

            for(int i = 0; i < services.size(); ++i) {
                BluetoothGattService bluetoothGattService = (BluetoothGattService)services.get(i);
                Iterator var6 = bluetoothGattService.getCharacteristics().iterator();

                while(var6.hasNext()) {
                    BluetoothGattCharacteristic characteristic = (BluetoothGattCharacteristic)var6.next();
                    int charaProp = characteristic.getProperties();
                    if ((charaProp & 16) != 0) {
                        Log.e(BleBlueToothPort.this.TAG, "发现NOTIFY特征值" + characteristic.getUuid().toString());
                        if (characteristic.getUuid().toString().equals(BleBlueToothPort.this.NOTIFY_UUID)) {
                            Log.e(BleBlueToothPort.this.TAG, "设置飞易通NOTIFY特征值" + characteristic.getUuid().toString());
                            BleBlueToothPort.this.notifyCharacteristic = characteristic;
                        } else {
                            Log.e(BleBlueToothPort.this.TAG, "设置其他NOTIFY特征值" + characteristic.getUuid().toString());
                            BleBlueToothPort.this.notifyCharacteristic = characteristic;
                        }

                        BleBlueToothPort.this.enableNotification(true, BleBlueToothPort.this.notifyCharacteristic);
                    }

                    if ((charaProp & 8) != 0) {
                        Log.e(BleBlueToothPort.this.TAG, "发现Write特征值" + characteristic.getUuid().toString());
                        if (characteristic.getUuid().toString().equals(BleBlueToothPort.this.WRITE_UUID)) {
                            Log.e(BleBlueToothPort.this.TAG, "设置飞易通Write特征值" + characteristic.getUuid().toString());
                            BleBlueToothPort.this.writeCharacteristic = characteristic;
                        } else {
                            Log.e(BleBlueToothPort.this.TAG, "设置其他Write特征值：" + characteristic);
                            BleBlueToothPort.this.writeCharacteristic = characteristic;
                        }
                    }
                }
            }

            if (BleBlueToothPort.this.notifyCharacteristic != null) {
                Log.e(BleBlueToothPort.this.TAG, "获取writeCharacteristic成功");
                (new Thread(new Runnable() {
                    public void run() {
                        if (BleBlueToothPort.this.callbackListener != null) {
                            if (BleBlueToothPort.this.command == null) {
                                UIThreadManager.onUIThread(new Runnable() {
                                    public void run() {
                                        BleBlueToothPort.this.callbackListener.onCheckCommand();
                                    }
                                });

                                try {
                                    BleBlueToothPort.this.checkPrinterCommand();
                                } catch (IOException var2) {
                                }
                            } else {
                                BleBlueToothPort.this.setSuccessListen(BleBlueToothPort.this.command);
                            }
                        }

                    }
                })).start();
            } else {
                Log.e(BleBlueToothPort.this.TAG, "获取writeCharacteristic失败");
                BleBlueToothPort.this.setFailureListen();
            }

        }

        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicRead(gatt, characteristic, status);
        }

        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicWrite(gatt, characteristic, status);
            if (status == 0) {
                byte[] rec = characteristic.getValue();
                Log.e(BleBlueToothPort.this.TAG, "已发送:\t" + HexUtils.byte2HexStr(rec));
            } else {
                Log.e(BleBlueToothPort.this.TAG, "Send data failed!");
            }

        }

        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            super.onCharacteristicChanged(gatt, characteristic);
            final byte[] rec = characteristic.getValue();
            UIThreadManager.onUIThread(new Runnable() {
                public void run() {
                    BleBlueToothPort.this.callbackListener.onReceive(rec);
                }
            });
            Log.e(BleBlueToothPort.this.TAG, "接收到信息" + HexUtils.byte2HexStr(rec));
            if (rec.length > 0) {
                synchronized(BleBlueToothPort.this.lock) {
                    try {
                        BleBlueToothPort.this.byteArrayOutputStream.write(rec);
                    } catch (IOException var7) {
                        var7.printStackTrace();
                    }

                    BleBlueToothPort.this.lock.notifyAll();
                }
            }

        }

        public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            super.onDescriptorRead(gatt, descriptor, status);
            Log.e(BleBlueToothPort.this.TAG, "onDescriptorRead" + String.format("%02X", descriptor.getValue()));
        }

        public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
            Log.e(BleBlueToothPort.this.TAG, "mtu" + mtu);
        }
    }
}
